package com.tanhua.dubbo.api;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.dubbo.utils.TimeLineService;
import com.tanhua.model.mongo.Friend;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.MovementTimeLine;
import com.tanhua.model.vo.PageResult;
import org.apache.dubbo.config.annotation.DubboService;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.SampleOperation;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.List;

@DubboService
public class MovementApiImpl implements MovementApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private TimeLineService timeLineService;


    //保存动态
    public String save(Movement movement) {
        //1.保存动态数据
        mongoTemplate.save(movement);
        //获取动态id
        ObjectId movementId = movement.getId();
        //2.根据用户id查询用户的好友列表
        //获取用户id
        //3.保存好友--动态关系数据--以多线程处理
        Long userId = movement.getUserId();
        timeLineService.saveTimeLine(userId, movementId);
        return movementId.toString();
    }

    //查询个人动态
    public List<Movement> findByUserId(Integer page, Integer pagesize, Long userId) {

        Criteria criteria = Criteria.where("userId").is(userId).and("state").is(1);
        Query query = Query.query(criteria)
                .with(Sort.by(Sort.Order.desc("created")))//排序
                .skip((page - 1) * pagesize)//初始页
                .limit(pagesize);//页大小

        return mongoTemplate.find(query, Movement.class);
    }

    //查询好友动态
    public List<Movement> findByFriendId(Long friendId, Integer page, Integer pagesize) {
        //1.分页查询时间线表
        Criteria lineCriteria = Criteria.where("friendId").is(friendId).and("state").is(1);
        Query lineQuery = Query.query(lineCriteria)
                .with(Sort.by(Sort.Order.desc("created")))//排序
                .skip((page - 1) * pagesize)//初始页
                .limit(pagesize);//页大小
        List<MovementTimeLine> timeLines = mongoTemplate.find(lineQuery, MovementTimeLine.class);
        //2.从timeLiness中提取所有的动态id
        List<ObjectId> movementIds = CollUtil.getFieldValues(timeLines, "movementId", ObjectId.class);
        //3.根据所有动态id。查询动态的列表数据(详情)   多个不一样的数据使用in
        Criteria movementCriteria = Criteria.where("id").in(movementIds);
        Query query = Query.query(movementCriteria);
        return mongoTemplate.find(query, Movement.class);
    }

    //根据动态id，分页查询数据
    public List<Movement> findByIds(String[] movementIds, Integer page, Integer pagesize) {
        Criteria criteria = Criteria.where("id").in(movementIds).and("state").is(1);//mongodb对于主键在做。 is，in 查询时，不需要转成ObjectId
        //通过分析推荐列表不需要排序
        Query query = Query.query(criteria)
                .skip((page - 1) * pagesize)//初始页
                .limit(pagesize);//页大小
        return mongoTemplate.find(query, Movement.class);
    }

    //随机获取（使用频次不多）
    public List<Movement> randomMovement(Integer counts) {
        //定义统计类型
        SampleOperation operation = Aggregation.sample(counts);//随机  统计采样

        //设置统计的方式
        TypedAggregation<Movement> aggregation = TypedAggregation.newAggregation(Movement.class, operation);//设计统计的方式

        //统计，将统计结果封装到了results对象中
        AggregationResults<Movement> results = mongoTemplate.aggregate(aggregation, Movement.class);
        //从封装对象中获取统计结果
        return results.getMappedResults();
    }

    //根据id查询动态
    public Movement findById(String movementId) {
        //根据id查询使用findById方法，   因为movementId是String类型需要new一个ObjectId
        return mongoTemplate.findById(new ObjectId(movementId), Movement.class);
    }

    //更新动态状态
    public void updateState(String movementId, Integer state) {
        Criteria criteria = Criteria.where("id").is(new ObjectId(movementId));
        Query query = Query.query(criteria);
        Update update = new Update();
        update.set("state", state);
        mongoTemplate.updateFirst(query, update, Movement.class);

    }

    //分页查询动态列表
    public PageResult findAll(Integer state, Long userId, Integer page, Integer pagesize) {
        Criteria criteria = new Criteria();
        //对请求参数进行判断，可能传过来的是空
        if (state != null) {
            criteria.and("state").is(state);
        }
        if (userId != null) {
            criteria.and("userId").is(userId);
        }
        Query query = Query.query(criteria);
        long count = mongoTemplate.count(query, Movement.class);
        query.with(Sort.by(Sort.Order.desc("created")))
                .skip((page - 1) * pagesize)
                .limit(pagesize);
        List<Movement> list = mongoTemplate.find(query, Movement.class);
        return new PageResult(page, pagesize, count, list);
    }
}
